package com.collect.zambia.zhiUtils.zhiApkDownload;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.core.content.ContextCompat;

import com.collect.zambia.R;
import com.collect.zambia.zhiHelper.ZHISysShareHelper;
import com.collect.zambia.zhiUtils.PackageUtil;
import com.collect.zambia.zhiUtils.ToastUtil;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


public class ApkDownloader {

    private static final int STATE_SUCCESS = -1;
    private static final int STATE_ERROR = -2;

    private Context context;
    private Context applicationContext;
    private ApkInfo apkInfo;
    private int fileLength;
    private int currLength;

    private boolean isGoOn;
    private int lastProgress = 0;
    private OnDownLoadListener onDownLoadListener;

    private ApkDialog apkDialog = new ApkDialog();
    private NotificationHelper notificationHelper;

    private static final List<String> downloadManager = new ArrayList<>();

    public ApkDownloader(Context context, ApkInfo apkInfo) {
        this.context = context;
        this.apkInfo = apkInfo;
        this.applicationContext = context.getApplicationContext();
        this.apkDialog = new ApkDialog();
    }

    public boolean checkPermission() {
        List<String> permissions = new ArrayList<>();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
        }
        permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);

        for (String permission : permissions) {
            if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(context, permission)) {
                return false;
            }
        }

        return true;
    }

    public void downloadApk() {
        if (checkPermission()) {
            if (!apkInfo.apkInstallUrl.endsWith(".apk")) {
                try {
                    ZHISysShareHelper.shareOnBrowser(context, apkInfo.apkInstallUrl);
                    ToastUtil.l("1 "+context.getResources().getString(R.string.to_sys_brower_view_the_download_progress));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return;
            }

            synchronized (downloadManager) {
                if (downloadManager.contains(apkInfo.appId)) {
                    ToastUtil.l(apkInfo.apkName + context.getResources().getString(R.string.downloading_now));
                    return;
                }
                downloadManager.add(apkInfo.appId);
            }
            try {
                init();
                beginDownload();
            } catch (Exception ex) {
                ex.printStackTrace();
                try {
                    synchronized (downloadManager) {
                        downloadManager.remove(apkInfo.appId);
                    }
                    ZHISysShareHelper.shareOnBrowser(context, apkInfo.apkInstallUrl);
                    ToastUtil.l("2 "+context.getResources().getString(R.string.to_sys_brower_view_the_download_progress));
                } catch (Exception ex2) {
                    ex2.printStackTrace();
                }
            }
        } else {
            try {
                ZHISysShareHelper.shareOnBrowser(context, apkInfo.apkInstallUrl);
                ToastUtil.l("3 "+context.getResources().getString(R.string.to_sys_brower_view_the_download_progress));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void init() {
        this.notificationHelper = new NotificationHelper(applicationContext, apkInfo).createBuilder(true);
        this.onDownLoadListener = new OnDownLoadListener() {
            @Override
            public void onProgress(int progress) {
                try {
                    apkDialog.showDownloadDialog(context, progress);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

                if (notificationHelper != null) {
                    notificationHelper.setContentTitle(PackageUtil.getName(applicationContext));
                    notificationHelper.setContentText(apkInfo.apkName + context.getResources().getString(R.string.did_downloaded) + progress + "%");
                    notificationHelper.notifyNotification(progress);
                }
            }

            @Override
            public void onSuccess() {
                synchronized (downloadManager) {
                    downloadManager.remove(apkInfo.appId);
                }

                try {
                    apkDialog.dismissDownloadDialog();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

                if (notificationHelper != null) {
                    notificationHelper.cancel();
                }
                notificationHelper = new NotificationHelper(applicationContext, apkInfo).createBuilder(false);
                notificationHelper.setContentIntent(ApkDownloadHelper.getInstallApkIntent(applicationContext, apkInfo.apkLocalUrl));
                notificationHelper.setContentTitle(PackageUtil.getName(applicationContext));
                notificationHelper.setContentText(context.getResources().getString(R.string.download_finish_install) + "（" + apkInfo.apkName + "）");
                notificationHelper.notifyNotification();
                boolean result = ApkDownloadHelper.installApk(applicationContext, apkInfo.apkLocalUrl);
                if (!result) {
                    ZHISysShareHelper.shareOnBrowser(context, apkInfo.apkInstallUrl);
                    ToastUtil.l("4 "+context.getResources().getString(R.string.to_sys_brower_view_the_download_progress));
                }
            }

            @Override
            public void onError() {
                synchronized (downloadManager) {
                    downloadManager.remove(apkInfo.appId);
                }

                try {
                    apkDialog.dismissDownloadDialog();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                if (notificationHelper != null) {
                    notificationHelper.cancel();
                }
                ZHISysShareHelper.shareOnBrowser(context, apkInfo.apkInstallUrl);
                ToastUtil.l("5 "+context.getResources().getString(R.string.to_sys_brower_view_the_download_progress));
            }
        };
    }

    private void beginDownload() {
        new Thread() {
            /**
             * 连接超时时长
             */
            public static final int CONNECT_TIMEOUT = 60 * 1000;

            /**
             * 读取超时时长
             */
            public static final int READ_TIMEOUT = 60 * 1000;

            private int length(String url) throws IOException {
                return length(url, 0);
            }

            private int length(String url, int count) throws IOException {
                HttpURLConnection readConnection = null;
                try {
                    readConnection = (HttpURLConnection) new URL(url).openConnection();
                    readConnection.setRequestMethod("GET");
                    readConnection.setDoInput(true);
                    readConnection.setDoOutput(false);
                    readConnection.setConnectTimeout(CONNECT_TIMEOUT);
                    readConnection.setReadTimeout(READ_TIMEOUT);
                    readConnection.connect();
                    if (readConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        return readConnection.getContentLength();
                    } else if (readConnection.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM
                            || readConnection.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP) {
                        apkInfo.apkInstallUrl = readConnection.getHeaderField("Location");
                        if (count < 3) {
                            return length(apkInfo.apkInstallUrl);
                        }
                    }
                } finally {
                    if (readConnection != null) {
                        readConnection.disconnect();
                    }
                }
                return -1;
            }

            @Override
            public void run() {
                super.run();

                HttpURLConnection conn = null;
                try {
                    fileLength = length(apkInfo.apkInstallUrl);

                    isGoOn = true;
                    conn = (HttpURLConnection) new URL(apkInfo.apkInstallUrl).openConnection();
                    conn.setConnectTimeout(10000);

                    conn.setRequestMethod("GET");
                    currLength = ApkDownloadHelper.getCurrLengthValue(applicationContext, apkInfo.appId);
                    conn.setRequestProperty("Range", "bytes=" + currLength + "-" + fileLength);
                    if (conn.getResponseCode() == HttpURLConnection.HTTP_PARTIAL
                            || conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        InputStream is = conn.getInputStream();
                        RandomAccessFile raf = new RandomAccessFile(apkInfo.apkLocalUrl, "rwd");
                        raf.setLength(fileLength);
                        raf.seek(currLength);

                        int len;
                        int lastProgress = 0;
                        byte[] buffer = new byte[1024];

                        while ((len = is.read(buffer)) != -1) {
                            if (!isGoOn) {
                                break;
                            }

                            if (onDownLoadListener != null) {
                                currLength += len;
                                int progress = (int) ((float) currLength / (float) fileLength * 100);
                                if (lastProgress != progress) {
                                    lastProgress = progress;
                                    handler.sendEmptyMessage(progress);
                                }
                            }

                            raf.write(buffer, 0, len);
                        }

                        ApkDownloadHelper.closeQuietly(is, raf);

                        if (!isGoOn && currLength < fileLength) {
                            ApkDownloadHelper.putCurrLengthValue(applicationContext, apkInfo.appId, currLength);
                        } else {
                            ApkDownloadHelper.removeCurrLengthValue(applicationContext, apkInfo.appId);
                            handler.sendEmptyMessage(100);
                            handler.sendEmptyMessage(STATE_SUCCESS);
                        }
                    } else if (conn.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM
                            || conn.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP) {
                        String location = conn.getHeaderField("Location");

                    } else {
                        ApkDownloadHelper.removeCurrLengthValue(applicationContext, apkInfo.appId);
                        handler.sendMessage(handler.obtainMessage(STATE_ERROR, "6 "+context.getResources().getString(R.string.to_sys_brower_view_the_download_progress)));
                    }

                    conn.disconnect();
                } catch (Exception e) {
                    ApkDownloadHelper.removeCurrLengthValue(applicationContext, apkInfo.appId);
                    handler.sendEmptyMessage(STATE_ERROR);
                } finally {
                    isGoOn = false;
                    if (conn != null) {
                        conn.disconnect();
                    }
                }
            }
        }.start();
    }

    public boolean isGoOn() {
        return isGoOn;
    }

    public boolean isGoOnWithAppId(String appId) {
        return isGoOn && apkInfo.appId.equalsIgnoreCase(appId);
    }

    public void cancel() {
        isGoOn = false;
    }

    public void setOnDownLoadListener(OnDownLoadListener onDownLoadListener) {
        this.onDownLoadListener = onDownLoadListener;
    }

    public interface OnDownLoadListener {
        void onProgress(int progress);

        void onSuccess();

        void onError();
    }

    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            if (onDownLoadListener != null) {
                switch (msg.what) {
                    case STATE_SUCCESS:
                        onDownLoadListener.onSuccess();
                        break;
                    case STATE_ERROR:
                        onDownLoadListener.onError();
                        if (msg.obj != null && msg.obj instanceof String) {
                            //ToastUtil.l((String)msg.obj);
                        }
                        break;
                    default:
                        if (lastProgress != msg.what) {
                            lastProgress = msg.what;
                            onDownLoadListener.onProgress(msg.what);
                        }
                        break;
                }
            }
        }
    };
}
